import { Checkbox, Select, message } from 'antd';
import { useState, useRef, useEffect } from 'react';

const { Option } = Select;

export interface RatioConfig {
    width: { exact: number };
    height: { exact: number };
}

export interface ResolutionConfig {
    label: string;
    type: string;
    ratio: RatioConfig;
}

const resolutions: ResolutionConfig[] = [
    {
        label: '320x240',
        type: 'QVGA',
        ratio: { width: { exact: 320 }, height: { exact: 240 } },
    },
    {
        label: '640x480',
        type: 'VGA',
        ratio: { width: { exact: 640 }, height: { exact: 480 } },
    },
    {
        label: '1280x720',
        type: '720P-HD',
        ratio: { width: { exact: 1280 }, height: { exact: 720 } },
    },
    {
        label: '1920x1080',
        type: '1080P-FullHD',
        ratio: { width: { exact: 1920 }, height: { exact: 1080 } },
    },
    {
        label: '2560x1440',
        type: '2K',
        ratio: { width: { exact: 2560 }, height: { exact: 1440 } },
    },
    {
        label: '4096x2160',
        type: '4K',
        ratio: { width: { exact: 4096 }, height: { exact: 2160 } },
    },
    {
        label: '7680x4320',
        type: '8K',
        ratio: { width: { exact: 7680 }, height: { exact: 4320 } },
    },
];

const ratioMap = (() => {
    const result: Record<string, ResolutionConfig> = {};
    resolutions.forEach(item => {
        result[item.type] = item;
    });
    return result;
})();

const ResolutionRatio = () => {
    const [config, setConfig] = useState(ratioMap.VGA);
    const dynamicRef = useRef(false);
    const videoRef = useRef<HTMLVideoElement>(null);
    const streamRef = useRef<MediaStream | null>(null);

    const handleChange = (value: string) => {
        console.log('value ----> ', value);
        setConfig(ratioMap[value]);
    }

    const dynamicRatio = (tracks: MediaStreamTrack[]) => {
        /** 动态改变分辨率 */
        const videoTrack = tracks[0];
        // https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack/applyConstraints
        videoTrack.applyConstraints(config.ratio).then(() => {
            message.success('切换成功');
        }).catch(e => {
            console.log('applyConstraints error: ', e);
            message.error('应用失败 >_<', e);
        });
    }

    const openCamrea = () => {
        navigator.mediaDevices.getUserMedia({
            video: config.ratio,
            audio: false,
        }).then((mediaStream) => {
            streamRef.current = mediaStream;
            videoRef.current!.srcObject = mediaStream;
        }).catch(e => {
            if (e.name === 'OverconstrainedError') {
                message.info('相机不支持该分辨率');
            }
        });
    }

    useEffect(() => {
        // 如果之前已经调用过 getUserMedia 拿到了流，先把之前的流停掉
        const stream = streamRef.current;
        if (stream) {
            const tracks = stream.getTracks();
            // 动态设置
            if (dynamicRef.current) return dynamicRatio(tracks);
            tracks.forEach(track => {
                // 停止播放轨道对应的源，源与轨道将脱离关联，同时轨道状态将设为“ended”。
                track.stop();
            });
            openCamrea();
        } else {
            openCamrea();
        }
    }, [config.ratio]);

    return (
        <div>
            分辨率：<Select style={{ width: 120 }} defaultValue={config.type} onChange={handleChange}>
                {
                    resolutions.map(item => {
                        return <Option key={item.type}>{item.label}</Option>
                    })
                }
            </Select>&nbsp;&nbsp;
            <Checkbox onChange={(e) => { dynamicRef.current = e.target.checked }}>动态设置分辨率</Checkbox>
            <br /><br />

            <video controls autoPlay ref={videoRef}></video>
        </div>
    );
};

export default ResolutionRatio;
